﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI;

namespace WebFormsBinder
{
    class JQueryClientEngine<TEntity> : IClientEngine<TEntity>
    {
        StringBuilder _registrationScript = new StringBuilder();
        const string EngineInstanceName = "engine";

        public void RegisterJavascript(ClientScriptManager clientScriptManager, IEnumerable<AbstractBinding<TEntity>> Bindings, IJavascriptGenerator<TEntity> jsGenerator)
        {
            BeginRegistration();
            foreach (var b in Bindings)
            {
                RegisterValidator(b.JSTypeValidationCondition, "Bad type", new string[] { b.JSElement });
                
            }
            EndRegistration(clientScriptManager);
        }

        public void RegisterJavascript(ClientScriptManager clientScriptManager, IEnumerable<AbstractBinding<TEntity>> Bindings)
        {
            BeginRegistration();
            foreach (var b in Bindings)
                RegisterValidator(b.JSTypeValidationCondition, "Bad type", new string[] { b.JSElement });
            EndRegistration(clientScriptManager);
        }

        void BeginRegistration()
        {
            _registrationScript.AppendFormat("var {0} = new WebFormsBinder.Engine();", EngineInstanceName);
            _registrationScript.AppendLine();
        }

        void EndRegistration(ClientScriptManager csm)
        {
            csm.RegisterClientScriptBlock(GetType(), "ValidatorRegistration", _registrationScript.ToString(), true);
        }

        void RegisterValidator(string jsCondition, string message, string[] fields)
        {
            _registrationScript.AppendFormat("{0}.addValidator(function(){{return {1};}},'{2}',[",
                EngineInstanceName,
                jsCondition,
                EscapeString(message));

            for (int i = 0; i < fields.Length; ++i)
            {
                _registrationScript.AppendFormat("'{0}'", EscapeString(fields[i]));
                if (i + 1 != fields.Length)
                    _registrationScript.Append(",");
            }

            _registrationScript.AppendLine("]);");
        }

        string EscapeString(string s)
        {
            return s.Replace("\\", "\\\\").Replace("'", "\\'");
        }

        /*
         * var fieldValidators = {};
         * fieldValidators['clientId'] = {};
         * fieldValidators['clientId2'] = {};
         * 
         * var validators = {};
         * validators[validators.length] = function(){ return (blah == blah); };
         * fieldValidators['clientId'][fieldValidators['clientId'].length] = validators.length - 1;
         * 
         * 
         * var WebFormsBinder = {
         *     Validator : function(validator, message, fields) {
         *         this.validate = validator;
         *         this.message = message;
         *         this.fields = fields;
         *         
         *         this.validatesField = function(field) {
         *             for (var f in this.fields) {
         *                 if (f === field)
         *                     return true;
         *             }
         *             return false;
         *         };
         *         
         * 
         *     },
         *     
         *     Engine : function() {
         *         this.validators = [];
         *         
         *         $(function() {
         *         
         *         });
         *         
         *         this.addValidator = function(method, message, fields) {
         *             var validator = new WebFormsBinder.Validator(method, message, fields);
         *             this.validators[this.validators.length] = validator;
         *         };
         *         
         *         this.findValidatorsForField = function(id) {
         *             var validators = [];
         *             for (var v in this.validators) {
         *                 if (v.validatesField(id))
         *                     validators[validators.length] = v;
         *             }
         *             return validators;
         *         };
         *         
         *         this.setFieldValidity = function(id, valid) {
         *             if (valid)
         *                 $('#'+id).parent().removeClass('invalid');
         *             else
         *                 $('#'+id).parent().addClass('invalid');
         *         }
         *         
         *         this.fieldChanged = function(id) {
         *             var validators = this.findValidatorsForField(id);
         *             for (var v in validators) {
         *                 if (!v.validate()) {
         *                     this.setFieldValidity(id, false);
         *                     return;
         *                 }
         *             }
         *             this.setFieldValidity(id, true);d
         *         };
         *         
         *         this.setValidationResult = function(validationResults) {
         *         };
         *         
         *         this.formSubmitted = function() {
         *             var validationResults = {};
         *             for (var v in this.validators) {
         *                 if (!v.validate()) {
         *                     for (var field in v.fields) {
         *                         validationResults[field] = validationResults[field] || [];
         *                         validationResults[field][validationResults[field].length] = v.message;
         *                     }
         *                 }
         *             }
         *             this.setValidationResult(validationResults);
         *             return validationResults.length === 0;
         *         };
         *         
         *         // Events
         *         var engine = this;
         *         this._fieldOnChange = function() {
         *             engine.fieldChanged(this.id);
         *         };
         *         
         *         this._formOnSubmit = function() {
                        return engine.formSubmitted();
         *         };
         *     }
         * };
         * 
         */
    }
}
